package top.superflow.version.db

import java.util.concurrent.atomic.AtomicReference

import top.superflow.exception.RequestUnsupportedException
import top.superflow.verify.Ensure
import top.superflow.version.compare.suggestion.Suggestion
import top.superflow.version.db.compare.{EntityExtraIncompatible, MatchMissingAndExtraEntity, MetadataConsistencySuggestion}

import scala.collection.mutable.{ListBuffer, Map}

trait EntityVersion  extends Version with Ensure{
  
  val name : AtomicReference[String] = new AtomicReference[String]()
  
  val fields : Map[String, FieldVersion] = Map[String, FieldVersion]()
  
  val indexes : Map[String, IndexVersion] = Map[String, IndexVersion]()

  def compare (targetStructure : Any): Option[Suggestion] = {
    targetStructure match {

      case dvp : Option[_] =>{
        if(dvp == None || dvp.isEmpty){
          Some(new MetadataConsistencySuggestion(new EntityExtraIncompatible(this, null), new MatchMissingAndExtraEntity(this, null)))
        }else{
          this.compare(dvp.get)
        }
      }

      case ev: EntityVersion => {
        val suggestionsForChildren = getSuggestionsForChildren(ev)

        summarizeSuggestion(suggestionsForChildren)
      }

      case _ => {
        throw new RequestUnsupportedException(targetStructure)
      }
    }

  }

  def getSuggestionsForChildren (targetEntityVersion : EntityVersion): List[Suggestion] = {
    val possibleSuggestionList = ListBuffer[Suggestion]()

    for((fieldName , field) <- this.fields){
      val fieldFromTargetEntity = targetEntityVersion.getMatchedChild(field)

      val sgtForTheField = field.compare(fieldFromTargetEntity)

      if(!sgtForTheField.isEmpty){
         possibleSuggestionList += sgtForTheField.get
      }

    }

    for((indexName , index) <- this.indexes){
      val indexFromTarget = targetEntityVersion.getMatchedChild(index)
      val sgtForTheIndex = index.compare(indexFromTarget)

      if(!sgtForTheIndex.isEmpty){
         possibleSuggestionList += sgtForTheIndex.get
      }
    }
    possibleSuggestionList.toList
  }


  def getMatchedChild (childDataVersionKey : Any) : Option[Version] = {
    childDataVersionKey match {
      case index : IndexVersion => {
        this.indexes.get(index.name.get)
      }
      
      case field : FieldVersion => {
        this.fields.get(field.name.get)
      }
      
      case _ =>{
        None
      }
    }
  }
}